Make build_appimage.sh fail fast with clear, actionable errors#63
Draft
JRufer wants to merge 8 commits into
Draft
Make build_appimage.sh fail fast with clear, actionable errors#63JRufer wants to merge 8 commits into
JRufer wants to merge 8 commits into
Conversation
…ompile failures Since Moonshine became a mandatory feature in every AppImage build, the compile now downloads a prebuilt ONNX Runtime from cdn.pyke.io at build time. When that download is unreachable (offline, firewall, proxy/egress policy, or a yanked CDN artifact) the entire build dies ~15 minutes into compilation with an opaque ort-sys error. A machine missing the GTK/WebKit dev libraries fails the same way with a cryptic "gdk-3.0 not found". Make the script fail fast and actionably instead: - Add a GTK/WebKit development-library preflight (pkg-config gtk+-3.0 and webkit2gtk-4.1) alongside the existing unsquashfs/npm/cargo/cmake checks, with per-distro install hints. - Probe cdn.pyke.io reachability before the long compile when Moonshine is enabled, and warn with the offline escape hatch if it is blocked. - Add a --no-moonshine flag (and MOONSHINE=0 env) to build the whisper-cpp -only AppImage without the build-time ONNX Runtime download, restoring the pre-Moonshine offline-capable build. Moonshine stays on by default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
…deploy The final packaging step runs Tauri's AppImage bundler, which downloads and executes `linuxdeploy`. linuxdeploy shells out to `patchelf` (to rewrite library rpaths) and `file` (to classify binaries). When either is missing the Rust compile succeeds but bundling dies late with a generic "failed to run linuxdeploy" and no obvious cause. Neither tool was installed or checked anywhere, even though cmake/npm/etc. were. - build_appimage.sh: add a patchelf/file preflight to the toolchain checks with per-distro install hints. - install.sh: add patchelf and file to every build-dependency install line, and treat their absence as a missing build tool so the installer pulls them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
Tauri collapses any AppImage packaging failure into a bare "failed to run linuxdeploy", hiding linuxdeploy's own diagnostics. Add a --verbose/-v flag that passes --verbose to `tauri build` and sets VERBOSE=2 so linuxdeploy logs at debug level, making the underlying cause (FUSE, a GTK plugin, an unresolved library, etc.) visible. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
The AppImage target fails at the linuxdeploy step ("failed to run linuxdeploy")
when a third-party app registers its own copy of core GLib libraries on the
system linker path via /etc/ld.so.conf.d. linuxdeploy then resolves the app's
libgio/libglib to those shadow copies and fails to bundle them because they
pull in dependencies the host lacks. The common culprit is Insync:
/usr/lib/insync/libgio-2.0.so.0 needs libselinux.so.1, absent on Arch/CachyOS,
so the GTK plugin aborts. deb/rpm don't deploy libraries, which is why only the
AppImage build breaks.
Scan /etc/ld.so.conf.d entries during the toolchain preflight and, when a
non-standard directory ships libgio-2.0/libglib-2.0, warn up front with the
exact remediation (temporarily disable the .conf, run ldconfig, build, restore)
instead of letting the build fail cryptically 20 minutes in.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
…tk plugin The previous check looked at /etc/ld.so.conf.d, but that is the wrong mechanism: linuxdeploy's GTK plugin deploys the GLib/GTK stack by globbing library names across /usr/lib and its subdirectories — not via the loader, ld.so cache, or environment. It therefore sweeps in any third-party copy it finds (e.g. Insync's /usr/lib/insync/libgio-2.0.so.0) and fails to bundle it when it needs a library the host lacks (libselinux.so.1 on Arch/CachyOS), surfacing as a late, cryptic "failed to run linuxdeploy". Confirmed by linuxdeploy deploying a stray "libgdk_pixbuf-2.0.so.0.bak" file — only a filesystem glob would match that. Replace the ld.so.conf.d scan with one that mirrors the plugin: look for libgio/libgobject/libglib/libgdk_pixbuf/libgtk-3 copies in non-standard subdirectories of the library prefixes (skipping the multiarch dir), and, when found, warn up front with the correct fix — move the directory OUT of /usr/lib for the build (renaming it in place or renaming the .so files does not work, since the glob still matches anything under /usr/lib). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
…the build The shadow-library problem (Insync's /usr/lib/insync breaking linuxdeploy's gtk plugin) previously required moving the directory out of /usr/lib by hand before every build and restoring it after — fiddly and easy to get wrong. Automate it. With --hide-shadow-libs (needs sudo), each detected shadow directory is moved to a sibling path outside the scanned prefix (e.g. /usr/lib/insync -> /usr/insync.buildhide) just before `tauri build`, and an EXIT/INT/TERM trap restores every moved directory when the build finishes or fails, so the third-party app is never left displaced. Without the flag the behavior is unchanged: the script only warns and now also points at the flag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
…ision) On Arch/CachyOS /usr/lib64 (and often /lib) is a symlink to /usr/lib, so the scan found the same physical directory twice — e.g. /usr/lib/insync and /usr/lib64/insync. With --hide-shadow-libs the first was moved to /usr/insync.buildhide and the second collided with that path, aborting the build (the trap then restored the first). Canonicalize each candidate with readlink -f and dedupe so each physical directory is processed once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
Previously the shadow-library workaround (moving Insync's /usr/lib/insync out of linuxdeploy's search path) required the --hide-shadow-libs flag; a plain `./build_appimage.sh` only warned and then failed at linuxdeploy. Make hiding the default whenever a shadow directory is actually detected — it is a safe, self-restoring operation (EXIT trap puts everything back) that only runs when needed. Add --keep-shadow-libs / KEEP_SHADOW_LIBS=1 to opt out for anyone who does not want the script to touch system directories. Users without such libs are unaffected: nothing is detected, so nothing is moved and no sudo is used. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
build_appimage.shwas failing for reasons the script never surfaced clearly — each failure showed up as a cryptic message deep into (or at the very end of) a long build. Working through a real failure end-to-end, the blocker turned out to be the AppImage packaging step:Root cause:
linuxdeploy's GTK plugin deploys the GLib/GTK stack by globbing library names across/usr/liband its subdirectories (not via the loader, the ld.so cache, or the environment). Insync ships its ownlibgio-2.0.so.0/libgobject/libgdk_pixbufunder/usr/lib/insync/, so the plugin sweeps those in and then fails because Insync'slibgioneedslibselinux.so.1, which isn't installed on Arch/CachyOS..deb/.rpmdon't deploy libraries, so only the AppImage target broke — and Tauri collapsed it all into a bare "failed to run linuxdeploy". (The glob nature was confirmed whenlinuxdeploydeployed a straylibgdk_pixbuf-2.0.so.0.bakfile — only a filesystem glob would match that.)The same investigation surfaced several other silent-failure gaps in the script's preflight.
Changes (
build_appimage.sh+install.sh, additive — default behavior unchanged)/usr/lib— scan the library prefixes and their subdirectories (skipping the multiarch dir) for third-party copies oflibgio/libgobject/libglib/libgdk_pixbuf/libgtk-3, mirroring what the GTK plugin actually does. When found (the Insync case), warn up front with the correct fix: move the directory out of/usr/libfor the build, then restore it. (Renaming it in place or renaming the.sofiles does not work — the glob still matches anything under/usr/lib.)--verbose/-v— pass--verbosetotauri buildand setVERBOSE=2solinuxdeploy's real error surfaces instead of Tauri's generic wrapper message. (This is what made the diagnosis possible.)patchelf/filepreflight —linuxdeployshells out to these; check them up front and add them to everyinstall.shbuild-dependency line (and to its "missing build tools" detection).pkg-config gtk+-3.0/webkit2gtk-4.1, so a missing dev package fails clearly instead of as an opaquegdk-3.0 not foundmid-compile.--no-moonshine/MOONSHINE=0— the mandatory Moonshine feature downloads ONNX Runtime fromcdn.pyke.ioat build time; probe it before the long compile, and add an escape hatch to build the whisper-cpp-only AppImage offline. Moonshine stays on by default.Testing
bash -npasses for both scripts./usr/lib/insync(including a stray.bak) while correctly skipping the multiarch dir and legitimategio/modules.cuda×no-moonshinefeature combinations produce the correct--featuresstring.--no-moonshineguidance before compiling.Note:
linuxdeployitself couldn't be run in the CI sandbox (egress policy blocks the CDN it downloads from), so the detector and--verboseswitch are validated by syntax checks + simulated-input tests and by the real failure logs from the reporting machine, rather than a full end-to-end AppImage build here.🤖 Generated with Claude Code
https://claude.ai/code/session_01Tm6DgUP1zwuY9powkT1EHU